package OpenRate.db;
import OpenRate.OpenRate;
import OpenRate.exception.ExceptionHandler;
import OpenRate.exception.InitializationException;
import OpenRate.utils.PropertyUtils;
import javax.sql.DataSource;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* The data source is a a pooled collection of connections that can be used
* by elements of the framework.
*
* * @author ddijak
*/
public class HikariCPDataSource implements IDBDataSource
{
// The symbolic name is used in the management of the pipeline (control and
// thread monitoring) and logging.
private String SymbolicName = "HikariDataSource";
// reference to the exception handler
private ExceptionHandler handler;
// used to simplify logging and exception handling
public String message;
// -----------------------------------------------------------------------------------------------
// ------------------ Hikari Connection Pool specific configuration options ---------------------
// -----------------------------------------------------------------------------------------------
/**
* minimal number of connections per partition
*/
public static final String MIN_CONN_KEY = "MinPoolConnections";
public static final String DEFAULT_MIN_CONN = "5";
/**
* maximal number of connections
*/
public static final String MAX_CONN_KEY = "MaxPoolConnections";
public static final String DEFAULT_MAX_CONN = "10";
/**
* Max Connection Age in seconds
*/
public static final String CONN_TIMEOUT_KEY = "ConnectionTimeout";
public static final String DEFAULT_CONN_TIMEOUT = "30000";
/**
* pool name
*/
public static final String POOL_NAME_KEY = "Name";
public static final String DEFAULT_POOL_NAME = "HikariDefined";
// -----------------------------------------------------------------------------
// --------------------------- Implementation ---------------------------------
// -----------------------------------------------------------------------------
/**
* Constructor: log our version info to the audit system
*/
public HikariCPDataSource()
{
}
/**
* Create new data source from provided properties.
*
* @param ResourceName The name of the DataSourceFactory in the properties
* @param dataSourceName The name of the data source to create
* @return The created data source
* @throws OpenRate.exception.InitializationException
*/
@Override
public DataSource getDataSource(String ResourceName, String dataSourceName)
throws InitializationException
{
String db_url = null;
String driver = null;
String username = null;
String password = null;
String validationSQL = null;
OpenRate.getOpenRateFrameworkLog().debug("Creating new DataSource <" + dataSourceName + ">");
try
{
// get the connection parameters
db_url = PropertyUtils.getPropertyUtils().getDataSourcePropertyValue(dataSourceName, DB_URL_KEY);
driver = PropertyUtils.getPropertyUtils().getDataSourcePropertyValue(dataSourceName, DRIVER_KEY);
username = PropertyUtils.getPropertyUtils().getDataSourcePropertyValue(dataSourceName, USERNAME_KEY);
password = PropertyUtils.getPropertyUtils().getDataSourcePropertyValue(dataSourceName, PASSWORD_KEY);
validationSQL = PropertyUtils.getPropertyUtils().getDataSourcePropertyValue(dataSourceName, VALIDATION_QUERY_KEY);
if (db_url == null || db_url.isEmpty())
{
message = "Error recovering data source parameter <db_url> for data source <" + dataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,getSymbolicName());
}
if (driver == null || driver.isEmpty())
{
message = "Error recovering data source parameter <driver> for data source <" + dataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,getSymbolicName());
}
if (username == null || username.isEmpty())
{
message = "Error recovering data source parameter <username> for data source <" + dataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,getSymbolicName());
}
if (password == null)
{
message = "Error recovering data source parameter <password> for data source <" + dataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,getSymbolicName());
}
OpenRate.getOpenRateFrameworkLog().info("Creating DataSource <" + dataSourceName + "> using driver <" + driver + "> from URL <" + db_url + ">");
Class<?> driverClass = Class.forName(driver);
OpenRate.getOpenRateFrameworkLog().debug("jdbc driver loaded. name = <" + driverClass.getName() + ">");
}
catch (ClassNotFoundException cnfe)
{
message = "Driver class <" + driver + "> not found for data source <" + dataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,getSymbolicName());
}
// Initialize pool
HikariDataSource dataSource = new HikariDataSource();
// Set driver class
dataSource.setDriverClassName(driver);
//dataSource.setDataSourceClassName(dsName);
// Options with defaults
int minConn = Integer.parseInt(PropertyUtils.getPropertyUtils().getDataSourcePropertyValueDef(dataSourceName,MIN_CONN_KEY, DEFAULT_MIN_CONN));
int maxConn = Integer.parseInt(PropertyUtils.getPropertyUtils().getDataSourcePropertyValueDef(dataSourceName,MAX_CONN_KEY, DEFAULT_MAX_CONN));
Long connTimeOut = Long.parseLong(PropertyUtils.getPropertyUtils().getDataSourcePropertyValueDef(dataSourceName,CONN_TIMEOUT_KEY, DEFAULT_CONN_TIMEOUT));
String poolName = PropertyUtils.getPropertyUtils().getDataSourcePropertyValueDef(dataSourceName,POOL_NAME_KEY, DEFAULT_POOL_NAME);
// Perform the initialization
dataSource.setJdbcUrl(db_url);
dataSource.setUsername(username);
dataSource.setPassword(password);
// Pooling configuration
dataSource.setMaximumPoolSize(maxConn);
dataSource.setMinimumIdle(minConn);
dataSource.setConnectionTimeout(connTimeOut);
if (!poolName.equals("HikariDefined"))
{
dataSource.setPoolName(poolName);
}
if (validationSQL == null || validationSQL.isEmpty())
{
OpenRate.getOpenRateFrameworkLog().warning("No SQL validation statement found for Datasource <" + dataSourceName + ">");
}
else
{
dataSource.setConnectionTestQuery(validationSQL);
// Test the data source
try
{
Connection testConn = dataSource.getConnection();
PreparedStatement stmt = testConn.prepareStatement(validationSQL);
stmt.executeQuery();
// tidy up
stmt.close();
testConn.close();
}
catch (SQLException ex)
{
message = "Connection test failed for connection <" + dataSourceName + ">";
OpenRate.getOpenRateFrameworkLog().error(message);
throw new InitializationException(message,getSymbolicName());
}
}
return dataSource;
}
/**
* Set the exception handler for handling any exceptions.
*
* @param handler the handler to set
*/
@Override
public void setHandler(ExceptionHandler handler)
{
this.handler = handler;
}
/**
* @return the SymbolicName
*/
public String getSymbolicName()
{
return SymbolicName;
}
/**
* @param SymbolicName the SymbolicName to set
*/
public void setSymbolicName(String SymbolicName)
{
this.SymbolicName = SymbolicName;
}
/**
* @return the handler
*/
public ExceptionHandler getHandler()
{
return handler;
}
}